Questions
11 of 11
1Evaluate this claim: 'Cosine similarity and normalized dot product always produce identical rankings.' What subtlety do candidates often miss here?
2Many candidates assume increasing ef at query time always improves recall with only a linear latency cost. What's misleading about that assumption?
3Why is 'just add more RAM' not always a valid answer to a Qdrant performance question in a system design interview?
4A candidate claims that quantization always speeds up search. Under what conditions might quantization with rescoring actually be slower than searching un-quantized vectors?
5Why can two identical-looking filter queries - one using an indexed field, one using an equivalent but unindexed field - have wildly different performance, even though they return the same results?
6At billion-point scale, how would your indexing and sharding strategy differ from a design that works fine at ten million points?
7How would you architect a system to gracefully degrade - rather than fail outright - when a burst of traffic exceeds provisioned Qdrant capacity?
8What are the limits of a purely payload-filter-based multitenancy model, and at what point would you need to introduce dedicated shards or collections per tenant instead?
9How would you approach re-embedding a multi-billion-point production collection with a new embedding model with zero search downtime?
10When designing a retrieval system that combines dense, sparse, and multivector reranking at extreme scale, what's the single biggest cost driver you'd optimize first, and why?
11If you were asked to design Qdrant's filtered-HNSW search from scratch, what core problem would you need to solve, and what naive approach would you reject first?
11 / 11

If you were asked to design Qdrant's filtered-HNSW search from scratch, what core problem would you need to solve, and what naive approach would you reject first?

Solve filter-aware traversal; reject post-filtering and pre-filtering with brute force

The core problem is: given a filter that matches a subset of points, find the top-k nearest neighbors among the matching points, without scanning the entire collection and without missing relevant results. The naive approaches are two. The first is post-filtering: run the ANN search without the filter, retrieve the top-k, then discard the ones that do not match. This fails because the top-k may contain few or no matching points, especially for selective filters, so the result set is incomplete or empty. It also wastes work on non-matching candidates. The second is pre-filtering with brute force: find all the points that match the filter (via the payload index), then compute the exact distances to all of them, then take the top-k. This is correct but expensive: if the filter matches a large fraction of the collection, the brute-force scan is a full scan. The correct solution is a filter-aware traversal: modify the HNSW search so that the filter is evaluated during the graph traversal, and the traversal continues until it has found enough matching points to return the top-k. This is what Qdrant does, and it is the core problem that the design must solve.

The mechanism that makes filter-aware traversal work is that the traversal maintains a candidate list and a result list, and the result list is populated only with points that pass the filter. The traversal continues until the candidate list is exhausted (no unexplored neighbor is closer than the worst result) or the result list has k matching points. If the filter is selective, the traversal has to explore more of the graph to find enough matching points, so the effective search breadth increases. The payload index helps by identifying the matching set and by pruning segments that cannot match. The naive approaches fail because they do not integrate the filter into the traversal: post-filtering decouples the filter from the search, so it can miss matching points that are not in the top-k; pre-filtering with brute force decouples the search from the graph, so it loses the sub-linear property. The filter-aware traversal is the only approach that preserves both correctness and sub-linear search. The design must also handle the case where the filter matches a very large fraction of the collection: in that case, the filter-aware traversal behaves like an unfiltered search, and the payload index may not help. And the case where the filter matches a very small fraction: in that case, the traversal must explore a large portion of the graph, and the cost can approach a full scan, which is why the planner may choose a pre-filtering strategy in that case.

  1. 1

    Core problem: top-k nearest neighbors among the points that match a filter.

  2. 2

    Naive post-filtering: retrieve top-k, then discard non-matching; fails for selective filters.

  3. 3

    Naive pre-filtering with brute force: find matching points, then exact scan; fails for non-selective filters.

  4. 4

    Filter-aware traversal: evaluate the filter during the graph traversal, continue until k matches.

  5. 5

    Payload index: identifies the matching set, prunes segments, guides the traversal.

  6. 6

    Selectivity: selective filters force more exploration; non-selective filters add overhead without reducing candidates.

  7. 7

    Planner choice: for very selective filters, pre-filtering may be cheaper; for non-selective, filter-aware traversal.

  8. 8

    Correctness: the filter-aware traversal returns exactly the top-k among the matching points.

The trade-off is between correctness, latency, and the cost of the index. The filter-aware traversal preserves correctness but can be slow for selective filters. The payload index enables pruning but costs memory and slows writes. The planner's choice between filter-aware traversal and pre-filtering is a cost-based decision that depends on the selectivity and the index availability. The common mistakes are: (1) implementing post-filtering, which is wrong for selective filters; (2) implementing pre-filtering with brute force, which is correct but slow; (3) not using a payload index, so the traversal cannot prune; (4) not handling the very-selective case, where the traversal cost approaches a full scan; (5) not measuring the filter-aware traversal under different selectivities. Version note: the filter-aware traversal and the planner's behavior have evolved across Qdrant releases. The exact implementation and the performance characteristics differ. If you are designing a system from scratch, the filter-aware traversal is the core idea, but the details of the index and the planner are where the engineering effort goes.

javascript

Version-dependent: the filter-aware traversal and the planner's behavior have evolved across Qdrant releases. The exact implementation and the performance characteristics differ. If you are designing a system from scratch, the filter-aware traversal is the core idea, but the details of the index and the planner are where the engineering effort goes.

Difficulty: 9/10
Topics: Filtered HNSW, Query Execution, First Principles

Scenario Questions

0-2 years experience
  1. 1

    You are designing filtered search and your first idea is post-filtering. Explain why it fails.

  2. 2

    A teammate suggests brute-force pre-filtering. Explain when that is correct but slow.

2-5 years experience
  1. 1

    You implement filter-aware traversal and a selective filter is slow. Diagnose the cause and propose a fix.

  2. 2

    Your filter matches 90 percent of the collection. Explain whether the filter-aware traversal helps or hurts.

5-8 years experience
  1. 1

    Design the cost model for a planner that chooses between filter-aware traversal and pre-filtering, and describe the statistics it needs.

  2. 2

    You need to support a filter that combines a keyword match and a range condition. Describe how the traversal and the indexes interact.

8+ years experience
  1. 1

    Derive the expected cost of a filter-aware traversal as a function of filter selectivity, graph degree, and ef. Where does it become cheaper to pre-filter?

  2. 2

    You are designing the filtered search for a new vector database from scratch. Describe the data structures, the traversal, and the planner.

Follow-up Questions

  • How would the filter-aware traversal behave when the filter matches 99 percent of the collection, and how would the planner decide?
  • How would you extend the filter-aware traversal to handle a filter that requires a join with an external table?